#include "YXString.h"

#include <stdarg.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

char *yxString_printf(const char *format, ...) {
    // 初始化变量参数列表
    va_list args;
    va_start(args, format);

    // 使用vsprintf来计算最终的字符串长度
    va_list args_copy;
    va_copy(args_copy, args);
    int len = vsnprintf(NULL, 0, format, args_copy);
    va_end(args_copy);

    // 分配足够的内存来存储格式化后的字符串
    char *string = (char *) malloc(len + 1);

    // 使用vsprintf将格式化的字符串写入分配的内存
    vsprintf(string, format, args);
    va_end(args);

    // 返回最终的字符串
    return string;

}


// 手动实现 strdup
char* my_strdup(const char *str) {
    // 计算字符串长度并分配足够的空间
    size_t len = strlen(str) + 1;
    char *copy = (char *)malloc(len);
    if (copy != NULL) {
        memcpy(copy, str, len);  // 复制字符串
    }
    return copy;
}

// 定义一个函数，直接返回包含提取值的数组
char** extract_values(const char *query, int *count) {
    char *query_copy = my_strdup(query);  // 使用自定义的my_strdup函数创建字符串的副本
    char *token = strtok(query_copy, "&");  // 按照&符号拆分查询字符串
    char **result = (char **)malloc(10 * sizeof(char *));  // 假设最多提取10个值
    *count = 0;

    while (token != NULL) {
        // 每个token形如"key=value"，我们只关心=后面的value部分
        char *equal_sign = strchr(token, '=');
        if (equal_sign != NULL) {
            // 获取等号后面的部分作为值
            result[*count] = my_strdup(equal_sign + 1);  // 使用自定义的my_strdup
            (*count)++;
        }
        token = strtok(NULL, "&");  // 获取下一个token
    }

    free(query_copy);  // 释放复制的字符串
    return result;  // 返回结果数组
}

void url_decode(char *str) {
    char *p = str;
    char hex[3] = {0};
    while (*p) {
        if (*p == '%') {
            hex[0] = *(p + 1);
            hex[1] = *(p + 2);
            *p = (char)strtol(hex, NULL, 16); // 转换十六进制字符
            memmove(p + 1, p + 3, strlen(p + 3) + 1); // 移动后面的字符
        } else {
            p++;
        }
    }
}

// Function to find boundary in the Content-Type header
const char *find_boundary(const char *content_type) {
    const char *boundary_prefix = "boundary=";
    const char *boundary_start = strstr(content_type, boundary_prefix);
    if (boundary_start) {
        boundary_start += strlen(boundary_prefix);
        return boundary_start;
    }
    return NULL;
}

// Function to split string by delimiter and return the first part
char *split_by_boundary(char *data, const char *boundary) {
    char *start = strstr(data, boundary);
    if (start) {
        start += strlen(boundary);
        return start;
    }
    return NULL;
}

char *my_strndup(const char *str, size_t len) {
    // 为新字符串分配内存，+1 是为了存放 '\0' 结束符
    char *new_str = (char *)malloc(len + 1);
    if (new_str == NULL) {
        return NULL; // 如果内存分配失败，返回 NULL
    }
    // 将原字符串的前 len 个字符复制到新字符串
    strncpy(new_str, str, len);
    // 确保新字符串以 '\0' 结束
    new_str[len] = '\0';
    return new_str;
}

// Function to parse multipart data and store the parts in an array
MultipartData* parse_multipart_data(const char *body, const char *boundary) {
    MultipartData* result = malloc(sizeof(MultipartData));
    result->parts = NULL;
    result->part_count = 0;

    char *data = my_strdup(body);  // Make a copy of the body to manipulate
    char *part = split_by_boundary(data, boundary);

    while (part != NULL) {
        MultipartPart new_part = {0};

        // Skip headers (Content-Disposition, Content-Type, etc.)
        char *header_end = strstr(part, "\r\n\r\n");
        if (header_end != NULL) {
            *header_end = '\0';  // Split the headers and body
            part = header_end + 4;
        }

        // Allocate memory for new part and assign content
        new_part.content = my_strdup(part);
        new_part.content_length = strlen(part);

        // Parse headers to find name and filename
        char *name = strstr(part, "name=\"");
        if (name) {
            name += 6;  // Skip "name=\""
            char *end_name = strchr(name, '\"');
            if (end_name) {
                size_t name_length = end_name - name;
                new_part.name = my_strndup(name, name_length);
            }
        }

        char *filename = strstr(part, "filename=\"");
        if (filename) {
            filename += 10;  // Skip "filename=\""
            char *end_filename = strchr(filename, '\"');
            if (end_filename) {
                size_t filename_length = end_filename - filename;
                new_part.filename = my_strndup(filename, filename_length);
            }
        }

        // Add the new part to the result array
        result->parts = realloc(result->parts, sizeof(MultipartPart) * (result->part_count + 1));
        result->parts[result->part_count++] = new_part;

        // Move to the next part
        part = split_by_boundary(part, boundary);
    }

    free(data);
    return result;
}